package com.ly.heart.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ly.common.PageParam;
import com.ly.common.core.domain.AjaxResult;
import com.ly.common.core.domain.entity.SysDept;
import com.ly.common.exception.CustomException;
import com.ly.common.utils.DateUtils;
import com.ly.common.utils.SecurityUtils;
import com.ly.common.utils.StringUtils;
import com.ly.common.utils.erp.CommonUtil;
import com.ly.common.utils.erp.ConstUtil;
import com.ly.common.utils.erp.KingConstUtil;
import com.ly.common.utils.erp.SnowflakeIdWorker;
import com.ly.heart.domain.*;
import com.ly.heart.domain.dto.*;
import com.ly.common.core.domain.ActCurrentTaskVo;
import com.ly.heart.domain.vo.KingFinanceReceiptBillVo;
import com.ly.heart.mapper.*;
import com.ly.heart.service.*;
import com.ly.heart.util.CurrentUserUtil;
import com.ly.system.service.ISysDeptService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * 财务模块-应收票据,推金蝶Service业务层处理
 * @author wutao
 * @date 2024-06-19
 */
@Service
@Slf4j
public class KingFinanceReceiptBillServiceImpl extends ServiceImpl<KingFinanceReceiptBillMapper, KingFinanceReceiptBillEntity> implements IKingFinanceReceiptBillService {

    @Resource
    private KingFinanceReceiptBillMapper kingFinanceReceiptBillMapper;
    @Resource
    private IKingFinanceReceiptSettlementBillService iKingFinanceReceiptSettlementBillService;
    @Resource
    private IKingBaseCurrencyService iKingBaseCurrencyService;
    @Resource
    private IKingFinanceReceiptRefundService iKingFinanceReceiptRefundService;
    @Resource
    private KingFinanceReceiptBillReciteMapper kingFinanceReceiptBillReciteMapper;
    @Resource
    private IKingFinancePayService iKingFinancePayService;
    @Resource
    private IActModelService iActModelService;
    @Resource
    private ICustomerService iCustomerService;
    @Resource
    private ISupplierService iSupplierService;
    @Resource
    private IKingBaseTransactionsCompanyService iKingBaseTransactionsCompanyService;
    @Resource
    private ISysDeptService iSysDeptService;
    @Resource
    private IActTaskCommentService iActTaskCommentService;
    @Resource
    private IKingFinanceReceiptService iKingFinanceReceiptService;
    @Resource
    private IKingInvoiceReceivableOtherService iKingInvoiceReceivableOtherService;
    @Resource
    private IKingFinancePayRefundService iKingFinancePayRefundService;
    @Resource
    private IKingFinanceReceiptBillReciteService iKingFinanceReceiptBillReciteService;

    /**
     * 应收票据详情
     * @param id 财务模块-应收票据,推金蝶ID
     * @return 财务模块-应收票据,推金蝶
     */
    @Override
    public KingFinanceReceiptBillEntity selectKingFinanceReceiptBillEntityById (String id) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( id );
        String transactionCompanyName = getCompanyName ( receiptBillEntity.getPayDeptType (), receiptBillEntity.getPayDeptId () );
        receiptBillEntity.setPayDeptName ( transactionCompanyName );
        return receiptBillEntity;
    }

    /**
     * 应收票据列表
     * @param kingFinanceReceiptBillEntity 财务模块-应收票据,推金蝶
     * @return 财务模块-应收票据,推金蝶
     */
    @Override
    public AjaxResult selectKingFinanceReceiptBillEntityList (KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        kingFinanceReceiptBillEntity.setPage ( ( kingFinanceReceiptBillEntity.getPage () - 1 ) * kingFinanceReceiptBillEntity.getLimit () );
        List<KingFinanceReceiptBillEntity> kingFinanceReceiptBillEntities = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityList ( kingFinanceReceiptBillEntity );
        kingFinanceReceiptBillEntities.forEach ( receiptBill -> {
            String transactionCompanyName = getCompanyName ( receiptBill.getPayDeptType (), receiptBill.getPayDeptId () );
            receiptBill.setReceiptDeptName ( transactionCompanyName );
            //处理最后一个审批人
            ActTaskCommentEntity actTaskCommentEntity = iActTaskCommentService.queryLastComment ( receiptBill.getInstanceId () );
            if ( actTaskCommentEntity != null ) {
                receiptBill.setApprovedUser ( actTaskCommentEntity.getApprovedUser () );
                receiptBill.setApprovedRemark ( actTaskCommentEntity.getRemark () );
            }
            //任务信息
            ActCurrentTaskVo currentTaskVo = iActModelService.getCurrentTaskByInstanceId ( receiptBill.getInstanceId () );
            Optional.ofNullable ( currentTaskVo ).ifPresent ( currentTask -> {
                receiptBill.setCurrentTask ( currentTask );
            } );
        } );
        Integer integer = kingFinanceReceiptBillMapper.queryCount ( kingFinanceReceiptBillEntity );
        PageParam pageParam = new PageParam ();
        pageParam.setRecords ( kingFinanceReceiptBillEntities ).setTotal ( integer );
        return AjaxResult.success ( pageParam );
    }

    /**
     * 应收票据暂存
     * @param kingFinanceReceiptBillEntity 财务模块-应收票据,推金蝶
     * @return 结果
     */
    @Override
    public AjaxResult draft (KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        //到期日必须大于签发日
        boolean after = CommonUtil.isAfter ( kingFinanceReceiptBillEntity.getIssuanceTime (), kingFinanceReceiptBillEntity.getDueTime () );
        if ( ! after ) {
            return AjaxResult.error ( "到期日必须大于签发日" );
        }
        kingFinanceReceiptBillEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
        int count = this.count ();
        kingFinanceReceiptBillEntity.setBillSerialNumber ( "YSPJ".concat ( String.format ( "%08d", count ) ) );
        kingFinanceReceiptBillEntity.setDeptId ( CurrentUserUtil.getCompanyId () );
        kingFinanceReceiptBillEntity.setReceiptDeptId ( CurrentUserUtil.getCompanyId () );
        kingFinanceReceiptBillEntity.setSettlementDeptId ( CurrentUserUtil.getCompanyId () );
        kingFinanceReceiptBillEntity.setSaleDeptId ( CurrentUserUtil.getCompanyId () );
        kingFinanceReceiptBillEntity.setCreateTime ( DateUtils.getNowDate () );
        kingFinanceReceiptBillEntity.setSettlementStatus ( KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_EMPTY );
        kingFinanceReceiptBillEntity.setCreateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
        kingFinanceReceiptBillEntity.setState ( ConstUtil.STATE_IN_DRAFT );
        boolean save = this.save ( kingFinanceReceiptBillEntity );
        if ( ! save ) {
            return AjaxResult.error ( "新增应收票据失败！" );
        }
        return AjaxResult.success ( "新增应收票据成功", kingFinanceReceiptBillEntity.getId () );
    }

    /**
     * 应收票据提交
     * @param kingFinanceReceiptBillEntity
     * @return
     */
    @Override
    public AjaxResult submit (KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        if ( StringUtils.isBlank ( kingFinanceReceiptBillEntity.getId () ) ) {
            return AjaxResult.error ( "请先暂存该票据！" );
        }
        //创建审批流
        StartProcessDto startDto = new StartProcessDto ().
                setBusinessId ( kingFinanceReceiptBillEntity.getId () ).
                setBusinessType ( kingFinanceReceiptBillEntity.getBusinessType () ).setModelId ( kingFinanceReceiptBillEntity.getModelId () ).
                setBusinessName ( "应收票据_".concat ( kingFinanceReceiptBillEntity.getId () ) );
        String instanceId = iActModelService.startProcess ( startDto );
        kingFinanceReceiptBillEntity.setInstanceId ( instanceId );
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getState, ConstUtil.STATE_IN_PROCESS ).
                set ( KingFinanceReceiptBillEntity :: getInstanceId, instanceId ).
                eq ( KingFinanceReceiptBillEntity :: getId, kingFinanceReceiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "提交应收票据失败！" );
        }
        return AjaxResult.success ( "提交应收票据成功" );
    }


    /**
     * 应收票据审核
     * 1、生成收款单（待审核状态），【结算方式为：银行存单汇票】，【收款用途：预收款】
     * @param id
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult approve (String id) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( id );
        KingFinanceReceiptDto dto = new KingFinanceReceiptDto ();
        //1.生成收款单
        KingFinanceReceiptEntity financeReceiptEntity = new KingFinanceReceiptEntity ();
        financeReceiptEntity.setDocTypeCode ( KingConstUtil.RECEIPT_SALE_RECEIPT );
        financeReceiptEntity.setBusinessTime ( receiptBillEntity.getIssuanceTime () );
        financeReceiptEntity.setTransactionCompanyType ( "BD_Customer" );
        financeReceiptEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        financeReceiptEntity.setPayDeptType ( "BD_Customer" );
        financeReceiptEntity.setPayDeptId ( receiptBillEntity.getPayDeptId () );
        financeReceiptEntity.setKingBaseCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
        financeReceiptEntity.setCopeMoney ( receiptBillEntity.getFaceAmount () );
        financeReceiptEntity.setActualMoney ( receiptBillEntity.getFaceAmount () );
        financeReceiptEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
        financeReceiptEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
        financeReceiptEntity.setSaleCompanyId ( receiptBillEntity.getSaleOrgId () );
        financeReceiptEntity.setSourceDocType ( KingConstUtil.RECEIPT_TYPE_RECEIPT_BILL );
        //明细
        List<KingFinanceReceiptDetailEntity> receiptDetailEntities = new ArrayList<> ();
        KingFinanceReceiptDetailEntity receiptDetailEntity = new KingFinanceReceiptDetailEntity ();
        receiptDetailEntity.setKingSettlementTypeCode ( KingConstUtil.SETT_TYPE_YHCDHP );
        receiptDetailEntity.setReceiptPurposeCode ( KingConstUtil.PURPOSE_YSK );
        receiptDetailEntity.setCopeMoney ( receiptBillEntity.getFaceAmount () );
        receiptDetailEntity.setActualMoney ( receiptBillEntity.getFaceAmount () );
        receiptDetailEntity.setReceiptMoney ( receiptBillEntity.getFaceAmount () );
        receiptDetailEntity.setDiscountedMoney ( receiptBillEntity.getFaceAmount () );
        receiptDetailEntity.setSourceDocType ( KingConstUtil.RECEIPT_TYPE_RECEIPT_BILL );
        receiptDetailEntity.setSourceNo ( receiptBillEntity.getBillSerialNumber () );
        receiptDetailEntity.setSourceId ( receiptBillEntity.getId () );
        receiptDetailEntities.add ( receiptDetailEntity );
        dto.setKingFinanceReceiptEntity ( financeReceiptEntity );
        dto.setKingFinanceReceiptDetailEntities ( receiptDetailEntities );
        iKingFinanceReceiptService.draft ( dto );
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getState, ConstUtil.STATE_FINISH ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "应收票据审核状态修改失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 修改财务模块-应收票据,推金蝶
     * @param kingFinanceReceiptBillEntity 财务模块-应收票据,推金蝶
     * @return 结果
     */
    @Override
    public AjaxResult updateKingFinanceReceiptBillEntity (KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        kingFinanceReceiptBillEntity.setUpdateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
        kingFinanceReceiptBillEntity.setUpdateTime ( DateUtils.getNowDate () );
        boolean b = this.updateById ( kingFinanceReceiptBillEntity );
        if ( ! b ) {
            throw new CustomException ( "修改应收票据失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 应收票据拆分
     * 1、检查该父是否还够拆分，状态是否支持拆分
     * 2、新增多条子应收票据
     * 3、父应收票据状态改为《拆分》
     * @param kingFinanceReceiptBillDto
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult split (KingFinanceReceiptBillDto kingFinanceReceiptBillDto) {
        //1.源父应收票据修改状态
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillDto.getKingFinanceReceiptBillEntity ();
        receiptBillEntity = baseMapper.selectById ( receiptBillEntity );
        if ( receiptBillEntity == null ) {
            throw new RuntimeException ( "该应收票据已失效，请检查后重试！" );
        }
        if ( receiptBillEntity.getState ().equals ( ConstUtil.STATE_IN_DRAFT ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不可拆分！" );
        }
        if ( receiptBillEntity.getSettlementStatus () >= KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_SPILT ) {
            return AjaxResult.error ( "该票据已完成拆分，不可重复拆分！" );
        }
        //检查余额可够拆分
        List<KingFinanceReceiptBillEntity> kingFinanceReceiptBillEntities = kingFinanceReceiptBillDto.getKingFinanceReceiptBillEntities ();
        if ( CollectionUtils.isEmpty ( kingFinanceReceiptBillEntities ) ) {
            return AjaxResult.error ( "拆分后子票据不能为空！" );
        }
        double sum = kingFinanceReceiptBillEntities.stream ().mapToDouble ( s -> Double.parseDouble ( s.getFaceAmount () ) ).sum ();
        if ( sum != Double.parseDouble ( receiptBillEntity.getFaceAmount () ) ) {
            return AjaxResult.error ( "该票据拆分金额不匹配！" );
        }
        receiptBillEntity.setSettlementStatus ( KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_SPILT );
        int i = baseMapper.updateById ( receiptBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "修改父应收票据为【拆分】状态失败！" );
        }
        //2.新增两条子拆分应收票据
        int insert = updateReceiptBill ( kingFinanceReceiptBillEntities, receiptBillEntity );
        if ( insert == 0 ) {
            return AjaxResult.error ( "拆分应收票据失败！" );
        }
        return AjaxResult.success ( "拆分应收票据成功" );
    }

    /**
     * 应收票据背书
     * 1、根据应收票据生成应收票据结算单
     * 2、生成背书列表，校验
     * 3、根据背书类型生成对应的收款单或付款单
     * @param kingFinanceReceiptBillReciteDto
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult recite (KingFinanceReceiptBillReciteDto kingFinanceReceiptBillReciteDto) {
        KingFinanceReceiptSettlementBillEntity receiptSettlementBillEntity = kingFinanceReceiptBillReciteDto.getKingFinanceReceiptSettlementBillEntity ();
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( receiptSettlementBillEntity.getReceiptBillId () );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在！" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不可背书！" );
        }
        //1.应收票据结算单
        receiptSettlementBillEntity = assemble ( receiptSettlementBillEntity, receiptBillEntity );
        receiptSettlementBillEntity.setDocTypeCode ( KingConstUtil.KING_RECEIPT_BILL_BS );
        receiptSettlementBillEntity.setBizTime ( receiptSettlementBillEntity.getReciteDate () );
        receiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        receiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        receiptSettlementBillEntity.setReceiptBillType ( 1 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( receiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "应付票据生成应收票据结算单失败！" );
        }
        //2.背书明细列表
        List<KingFinanceReceiptBillReciteEntity> receiptBillReciteEntities = kingFinanceReceiptBillReciteDto.getKingFinanceReceiptBillReciteEntities ();
        int insert = updateReceiptBillRecite ( receiptBillReciteEntities, receiptBillEntity.getId () );
        if ( insert == 0 ) {
            return AjaxResult.error ( "该票据背书失败！" );
        }
        //3.根据背书类型生成对应的收款单或付款单，根据明细的背书类型计划生成什么单据：《付款单》还是《其他应收单》
        for ( KingFinanceReceiptBillReciteEntity receiptBillReciteEntity : receiptBillReciteEntities ) {
            if ( receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_TO_ADVANCE_CHARGE ||
                    receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_OFFSET_PAYABLE ) {
                KingFinancePayEntity payEntity = new KingFinancePayEntity ();
                payEntity.setDocTypeCode ( KingConstUtil.PAY_PURCHASE_PAY );
                payEntity.setTransactionCompanyType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                payEntity.setTransactionCompanyId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                payEntity.setReceiptDeptType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                payEntity.setReceiptDeptId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                payEntity.setBusinessTime ( receiptSettlementBillEntity.getReciteDate () );
                payEntity.setCopeMoney ( receiptSettlementBillEntity.getReciteAmount () );
                payEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
                payEntity.setPayDeptId ( receiptBillEntity.getSaleOrgId () );
                payEntity.setProcureCompanyId ( receiptBillEntity.getPayDeptId () );
                payEntity.setSourceDocType ( KingConstUtil.PAY_TYPE_RECEIPT_BILL );//应收票据背书后
                //付款单明细
                List<KingFinancePayDetailEntity> payDetailEntities = new ArrayList<> ();
                KingFinancePayDetailEntity payDetailEntity = new KingFinancePayDetailEntity ();
                payDetailEntity.setKingSettlementTypeCode ( KingConstUtil.SETT_TYPE_PJBS );//应收票据背书
                if ( receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_TO_ADVANCE_CHARGE ) {
                    payDetailEntity.setPayReceiptPurposeCode ( KingConstUtil.PURPOSE_YFK );//预付款
                } else {
                    payDetailEntity.setPayReceiptPurposeCode ( KingConstUtil.PURPOSE_PUR_PAY );//采购付款
                }
                payDetailEntity.setSourceDocType ( KingConstUtil.PAY_TYPE_RECEIPT_BILL );
                payDetailEntity.setSourceId ( receiptBillEntity.getId () );
                payDetailEntities.add ( payDetailEntity );
                KingFinancePayDto dto = new KingFinancePayDto ();
                dto.setKingFinancePayEntity ( payEntity );
                dto.setKingFinancePayDetailEntities ( payDetailEntities );
                iKingFinancePayService.draft ( dto );
            } else if ( receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_OTHER_RECEIPT ) {
                //生成其他应收单
                KingInvoiceReceivableOtherEntity receivableOtherEntity = new KingInvoiceReceivableOtherEntity ();
                receivableOtherEntity.setDocTypeCode ( KingConstUtil.KING_OTHER_RECEIVABLE );
                receivableOtherEntity.setBizTime ( receiptSettlementBillEntity.getReciteDate () );
                receivableOtherEntity.setDueTime ( receiptSettlementBillEntity.getReciteDate () );
                receivableOtherEntity.setTransactionCompanyType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                receivableOtherEntity.setTransactionCompanyId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                receivableOtherEntity.setKingBaseCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
                receivableOtherEntity.setTotalAmount ( receiptSettlementBillEntity.getReciteAmount () );
                receivableOtherEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
                receivableOtherEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
                receivableOtherEntity.setSaleCompanyId ( receiptBillEntity.getSaleOrgId () );
                receivableOtherEntity.setSourceType ( 2 );
                List<KingInvoicePayableReceivableOtherDetailEntity> receivableOtherDetailEntities = new ArrayList<> ();
                KingInvoicePayableReceivableOtherDetailEntity receivableOtherDetailEntity = new KingInvoicePayableReceivableOtherDetailEntity ();
                receivableOtherDetailEntity.setInvoiceType ( "0" );
                receivableOtherDetailEntity.setNoTaxAmount ( receiptSettlementBillEntity.getReciteAmount () );
                receivableOtherDetailEntity.setTotalAmount ( receiptSettlementBillEntity.getReciteAmount () );
                receivableOtherDetailEntity.setRemarks ( "应付票据背书转其他应收款" );
                receivableOtherDetailEntity.setSourceDocType ( 3 );
                receivableOtherDetailEntity.setSourceDocNo ( receiptBillEntity.getId () );//应收票据
                receivableOtherDetailEntities.add ( receivableOtherDetailEntity );
                KingInvoiceReceivableOtherDto dto = new KingInvoiceReceivableOtherDto ();
                dto.setKingInvoiceReceivableOtherEntity ( receivableOtherEntity );
                dto.setKingInvoicePayableReceivableOtherDetailEntities ( receivableOtherDetailEntities );
                iKingInvoiceReceivableOtherService.draft ( dto );
            }
        }
        //修改应收票据结算状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_RECITE ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "应收票据结算状态修改为背书失败！" );
        }
        return AjaxResult.success ( "该票据结算成功" );
    }


    /**
     * 获取背书退回数据
     * @param id
     * @return
     */
    @Override
    public KingFinanceReceiptBillVo getReciteRefund (String id) {
        KingFinanceReceiptBillVo vo = new KingFinanceReceiptBillVo ();
        KingFinanceReceiptSettlementBillEntity one = iKingFinanceReceiptSettlementBillService.getOne ( new LambdaQueryWrapper<KingFinanceReceiptSettlementBillEntity> ().
                eq ( KingFinanceReceiptSettlementBillEntity :: getReceiptBillId, id ).
                eq ( KingFinanceReceiptSettlementBillEntity :: getReceiptBillType, 1 ) );
        String transactionCompanyName = getCompanyName ( one.getEndorsedDeptType (), one.getEndorsedDeptId () );
        one.setEndorsedDeptName ( transactionCompanyName );
        KingBaseCurrencyEntity currency = iKingBaseCurrencyService.getOne ( new LambdaQueryWrapper<KingBaseCurrencyEntity> ().eq ( KingBaseCurrencyEntity :: getId, one.getKingBaseCurrencyId () ) );
        one.setKingBaseCurrencyName ( currency.getCurrencyName () );
        //背书列表
        List<KingFinanceReceiptBillReciteEntity> list = iKingFinanceReceiptBillReciteService.list ( new LambdaQueryWrapper<KingFinanceReceiptBillReciteEntity> ().
                eq ( KingFinanceReceiptBillReciteEntity :: getReceiptBillId, id ) );
        vo.setKingFinanceReceiptSettlementBillEntity ( one ).setKingFinanceReceiptBillReciteEntities ( list );
        return vo;
    }

    /**
     * 应收票据背书退回
     * 1、新建应收票据结算单
     * 2、生成原应收票据对应的单据，比如原应收票据生成了付款单，这里生成付款退款单；原应收票据生成了其他应收单
     * @param kingFinanceReceiptBillReciteDto
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public AjaxResult reciteRefund (KingFinanceReceiptBillReciteDto kingFinanceReceiptBillReciteDto) {
        KingFinanceReceiptSettlementBillEntity receiptSettlementBillEntity = kingFinanceReceiptBillReciteDto.getKingFinanceReceiptSettlementBillEntity ();
        //1.先查询应付票据状态，看是否支持贴现
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( receiptSettlementBillEntity.getReceiptBillId () );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在！" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        //只有状态是背书的才能进行背书退回
        if ( receiptBillEntity.getSettlementStatus () != KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_RECITE ) {
            return AjaxResult.error ( "单据还没有背书或者已经被退回，不能再次进行退回操作！" );
        }
        receiptSettlementBillEntity = assemble ( receiptSettlementBillEntity, receiptBillEntity );
        receiptSettlementBillEntity.setDocTypeCode ( KingConstUtil.KING_RECEIPT_BILL_BSTH );
        receiptSettlementBillEntity.setBizTime ( receiptSettlementBillEntity.getReciteRefundDate () );
        receiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        receiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        receiptSettlementBillEntity.setReceiptBillType ( 2 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( receiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "应收票据背书退回失败！" );
        }
        //根据明细行的背书类型，生成对应的相反单据
        for ( KingFinanceReceiptBillReciteEntity receiptBillReciteEntity : kingFinanceReceiptBillReciteDto.getKingFinanceReceiptBillReciteEntities () ) {
            if ( receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_TO_ADVANCE_CHARGE ||
                    receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_OFFSET_PAYABLE ) {
                // 生成采购业务退款单
                KingFinancePayRefundDto dto = new KingFinancePayRefundDto ();
                KingFinancePayRefundEntity financePayRefundEntity = new KingFinancePayRefundEntity ();
                financePayRefundEntity.setDocTypeCode ( KingConstUtil.PAY_REFUND_PUR_REFUND );
                financePayRefundEntity.setBusinessTime ( receiptSettlementBillEntity.getReciteRefundDate () );
                financePayRefundEntity.setTransactionCompanyType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                financePayRefundEntity.setTransactionCompanyId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                financePayRefundEntity.setPayDeptType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                financePayRefundEntity.setPayDeptId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                financePayRefundEntity.setCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
                financePayRefundEntity.setCopeRefundMoney ( receiptSettlementBillEntity.getReciteAmount () );
                financePayRefundEntity.setActualRefundMoney ( receiptSettlementBillEntity.getReciteAmount () );
                financePayRefundEntity.setSettlementCompanyId ( receiptBillEntity.getSettlementDeptId () );
                financePayRefundEntity.setPayCompanyId ( receiptBillEntity.getReceiptDeptId () );
                financePayRefundEntity.setSourceDocType ( 3 );
                //明细
                List<KingFinancePayRefundDetailEntity> financePayRefundDetailEntities = new ArrayList<> ();
                KingFinancePayRefundDetailEntity financePayRefundDetailEntity = new KingFinancePayRefundDetailEntity ();
                financePayRefundDetailEntity.setKingSettlementTypeCode ( KingConstUtil.SETT_TYPE_PJBS );
                financePayRefundDetailEntity.setPayPurposeCode ( KingConstUtil.PURPOSE_PUR_PAY );
                financePayRefundDetailEntity.setActualRefundMoney ( receiptSettlementBillEntity.getReciteAmount () );
                financePayRefundDetailEntity.setCopeRefundMoney ( receiptSettlementBillEntity.getReciteAmount () );
                financePayRefundDetailEntity.setRemarks ( "应收票据背书退回" );
                financePayRefundDetailEntity.setSourceDocType ( 3 );
                financePayRefundDetailEntity.setSourceId ( receiptBillEntity.getId () );
                financePayRefundDetailEntities.add ( financePayRefundDetailEntity );
                dto.setKingFinancePayRefundEntity ( financePayRefundEntity );
                dto.setKingFinancePayRefundDetailEntities ( financePayRefundDetailEntities );
                iKingFinancePayRefundService.draft ( dto );
                log.info ( "应收票据背书退回下推付款退款单成功。" );
            } else if ( receiptBillReciteEntity.getReciteType () == KingConstUtil.FINANCE_RECEIPT_BILL_RECITE_TYPE_OTHER_RECEIPT ) {
                //生成其他应收单
                KingInvoiceReceivableOtherEntity receivableOtherEntity = new KingInvoiceReceivableOtherEntity ();
                receivableOtherEntity.setDocTypeCode ( KingConstUtil.KING_OTHER_RECEIVABLE );
                receivableOtherEntity.setBizTime ( receiptSettlementBillEntity.getReciteDate () );
                receivableOtherEntity.setDueTime ( receiptSettlementBillEntity.getReciteDate () );
                receivableOtherEntity.setTransactionCompanyType ( receiptSettlementBillEntity.getEndorsedDeptType () );
                receivableOtherEntity.setTransactionCompanyId ( receiptSettlementBillEntity.getEndorsedDeptId () );
                receivableOtherEntity.setKingBaseCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
                receivableOtherEntity.setTotalAmount ( receiptBillReciteEntity.getReciteAmount () );
                receivableOtherEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
                receivableOtherEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
                receivableOtherEntity.setSaleCompanyId ( receiptBillEntity.getSaleOrgId () );
                receivableOtherEntity.setSourceType ( 3 );
                List<KingInvoicePayableReceivableOtherDetailEntity> receivableOtherDetailEntities = new ArrayList<> ();
                KingInvoicePayableReceivableOtherDetailEntity receivableOtherDetailEntity = new KingInvoicePayableReceivableOtherDetailEntity ();
                receivableOtherDetailEntity.setInvoiceType ( "0" );
                receivableOtherDetailEntity.setNoTaxAmount ( receiptBillReciteEntity.getReciteAmount () );
                receivableOtherDetailEntity.setTotalAmount ( receiptBillReciteEntity.getReciteAmount () );
                receivableOtherDetailEntity.setRemarks ( "应收票据背书退回转其他应收款" );
                receivableOtherDetailEntity.setSourceDocType ( 3 );
                receivableOtherDetailEntity.setSourceDocNo ( receiptBillEntity.getId () );//应收票据
                receivableOtherDetailEntities.add ( receivableOtherDetailEntity );
                KingInvoiceReceivableOtherDto dto = new KingInvoiceReceivableOtherDto ();
                dto.setKingInvoiceReceivableOtherEntity ( receivableOtherEntity );
                dto.setKingInvoicePayableReceivableOtherDetailEntities ( receivableOtherDetailEntities );
                iKingInvoiceReceivableOtherService.draft ( dto );
                log.info ( "应收票据背书退回转其他应收款成功" );
            }
        }
        //修改状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_RECITE_REFUND ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "应收票据结算状态修改为背书失败！" );
        }
        return AjaxResult.success ( "应收票据背书退回成功" );
    }

    /**
     * 应付票据贴现，使用源应付票据生成新的贴现票据
     * 票据结算状态是完全拆分，不允许背书，贴现以及到期收款！
     * @param kingFinanceReceiptSettlementBillEntity
     * @return
     */
    @Override
    public AjaxResult discount (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity) {
        //1.先查询应付票据状态，看是否支持贴现
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( kingFinanceReceiptSettlementBillEntity.getReceiptBillId () );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在！" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        if ( receiptBillEntity.getSettlementStatus () == KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_SPILT || receiptBillEntity.getSettlementStatus () == KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_DISCOUNT ) {
            return AjaxResult.error ( "票据结算状态是拆分或已贴现，不允许贴现！" );
        }
        //生成应收票据结算单
        kingFinanceReceiptSettlementBillEntity = assemble ( kingFinanceReceiptSettlementBillEntity, receiptBillEntity );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        kingFinanceReceiptSettlementBillEntity.setBillType ( KingConstUtil.SETT_TYPE_YHCDHP );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillType ( 3 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( kingFinanceReceiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "应付票据贴现失败！" );
        }
        //修改状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_DISCOUNT ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "应收票据结算状态修改为贴现失败！" );
        }
        return AjaxResult.success ( "应付票据贴现成功" );
    }


    /**
     * 到期收款，生成应收票据结算单
     * 检查是否能收款
     * @param kingFinanceReceiptSettlementBillEntity
     * @return
     */
    @Override
    public AjaxResult receipt (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( kingFinanceReceiptSettlementBillEntity.getReceiptBillId () );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在！" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        //生成应收票据结算单
        kingFinanceReceiptSettlementBillEntity = assemble ( kingFinanceReceiptSettlementBillEntity, receiptBillEntity );
        kingFinanceReceiptSettlementBillEntity.setDocTypeCode ( KingConstUtil.KING_RECEIPT_BILL_DQSK );
        kingFinanceReceiptSettlementBillEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
        kingFinanceReceiptSettlementBillEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
        kingFinanceReceiptSettlementBillEntity.setBizTime ( kingFinanceReceiptSettlementBillEntity.getReceiptDate () );
        kingFinanceReceiptSettlementBillEntity.setBillType ( KingConstUtil.SETT_TYPE_YHCDHP );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillType ( 4 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( kingFinanceReceiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "应收票据到期收款失败！" );
        }
        log.info ( "应收票据到期收款成功。" );
        //修改状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_DUE_RECEIPT ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "修改应收票据结算状态为到期收款失败！" );
        }
        return AjaxResult.success ( "应收票据到期收款成功" );
    }

    /**
     * 应收票据退票，生成应收票据结算单
     * @param kingFinanceReceiptSettlementBillEntity
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class)
    public AjaxResult refund (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectKingFinanceReceiptBillEntityById ( kingFinanceReceiptSettlementBillEntity.getReceiptBillId () );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在！" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        //查看是否为质押状态
        if ( receiptBillEntity.getSettlementStatus () == KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_PLEDGE ) {
            return AjaxResult.error ( "质押状态下的票据，不能进行退票操作！" );
        }
        kingFinanceReceiptSettlementBillEntity = assemble ( kingFinanceReceiptSettlementBillEntity, receiptBillEntity );
        kingFinanceReceiptSettlementBillEntity.setDocTypeCode ( KingConstUtil.KING_RECEIPT_BILL_REFUND );
        kingFinanceReceiptSettlementBillEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
        kingFinanceReceiptSettlementBillEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
        kingFinanceReceiptSettlementBillEntity.setBizTime ( kingFinanceReceiptSettlementBillEntity.getReceiptDate () );
        kingFinanceReceiptSettlementBillEntity.setBillType ( KingConstUtil.SETT_TYPE_YHCDHP );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillType ( 5 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( kingFinanceReceiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "应收票据退票" );
        }
        //根据单据类型：处理其他应收单或收款退款单
        if ( "1".equals ( kingFinanceReceiptSettlementBillEntity.getGenerateType () ) ) {
            //其他应收单
            KingInvoiceReceivableOtherDto dto = new KingInvoiceReceivableOtherDto ();
            KingInvoiceReceivableOtherEntity receivableOtherEntity = new KingInvoiceReceivableOtherEntity ();
            receivableOtherEntity.setDocTypeCode ( KingConstUtil.KING_OTHER_RECEIVABLE );
            receivableOtherEntity.setBizTime ( kingFinanceReceiptSettlementBillEntity.getRefundTime () );
            receivableOtherEntity.setDueTime ( kingFinanceReceiptSettlementBillEntity.getRefundTime () );
            receivableOtherEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
            receivableOtherEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
            receivableOtherEntity.setKingBaseCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
            receivableOtherEntity.setTotalAmount ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receivableOtherEntity.setSettlementDeptId ( receiptBillEntity.getSettlementDeptId () );
            receivableOtherEntity.setReceiptDeptId ( receiptBillEntity.getReceiptDeptId () );
            receivableOtherEntity.setSaleCompanyId ( receiptBillEntity.getSaleOrgId () );
            receivableOtherEntity.setSourceType ( 4 );
            List<KingInvoicePayableReceivableOtherDetailEntity> receivableOtherDetailEntities = new ArrayList<> ();
            KingInvoicePayableReceivableOtherDetailEntity receivableOtherDetailEntity = new KingInvoicePayableReceivableOtherDetailEntity ();
            receivableOtherDetailEntity.setInvoiceType ( "0" );
            receivableOtherDetailEntity.setNoTaxAmount ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receivableOtherDetailEntity.setTotalAmount ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receivableOtherDetailEntity.setRemarks ( "应收票据退票转其他应收款" );
            receivableOtherDetailEntity.setSourceDocType ( 4 );
            receivableOtherDetailEntity.setSourceDocNo ( receiptBillEntity.getId () );//应收票据
            receivableOtherDetailEntities.add ( receivableOtherDetailEntity );
            dto.setKingInvoiceReceivableOtherEntity ( receivableOtherEntity );
            dto.setKingInvoicePayableReceivableOtherDetailEntities ( receivableOtherDetailEntities );
            iKingInvoiceReceivableOtherService.draft ( dto );
            log.info ( "应收票据退票转其他应收款成功" );
        } else if ( "2".equals ( kingFinanceReceiptSettlementBillEntity.getGenerateType () ) ) {
            //生成收款退款单
            KingFinanceReceiptRefundDto dto = new KingFinanceReceiptRefundDto ();
            KingFinanceReceiptRefundEntity receiptRefundEntity = new KingFinanceReceiptRefundEntity ();
            receiptRefundEntity.setDocTypeCode ( KingConstUtil.RECEIPT_REFUND_SXTK );
            receiptRefundEntity.setBusinessTime ( kingFinanceReceiptSettlementBillEntity.getRefundTime () );
            receiptRefundEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
            receiptRefundEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
            receiptRefundEntity.setReceiptDeptType ( receiptBillEntity.getPayDeptType () );
            receiptRefundEntity.setReceiptDeptId ( receiptBillEntity.getPayDeptId () );
            receiptRefundEntity.setCurrencyCode ( receiptBillEntity.getKingBaseCurrencyCode () );
            receiptRefundEntity.setCopeRefundMoney ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receiptRefundEntity.setActualRefundMoney ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receiptRefundEntity.setSettlementCompanyId ( receiptBillEntity.getSettlementDeptId () );
            receiptRefundEntity.setPayCompanyId ( receiptBillEntity.getReceiptDeptId () );
            receiptRefundEntity.setSaleCompanyId ( receiptBillEntity.getSaleOrgId () );
            List<KingFinanceReceiptRefundDetailEntity> receiptRefundDetailEntities = new ArrayList<> ();
            KingFinanceReceiptRefundDetailEntity receiptRefundDetailEntity = new KingFinanceReceiptRefundDetailEntity ();
            receiptRefundDetailEntity.setKingSettlementTypeCode ( KingConstUtil.SETT_TYPE_PJTP );
            receiptRefundDetailEntity.setReceiptPurposeCode ( KingConstUtil.PURPOSE_SALE_RECEIPT );
            receiptRefundDetailEntity.setCopeRefundMoney ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receiptRefundDetailEntity.setActualRefundMoney ( kingFinanceReceiptSettlementBillEntity.getReceiptAmount () );
            receiptRefundDetailEntity.setRemarks ( "应收票据退票转收款退款单" );
            receiptRefundDetailEntities.add ( receiptRefundDetailEntity );
            dto.setKingFinanceReceiptRefundEntity ( receiptRefundEntity );
            dto.setKingFinanceReceiptRefundDetailEntities ( receiptRefundDetailEntities );
            iKingFinanceReceiptRefundService.draft ( dto );
            log.info ( "应收票据退票转收款退款单成功" );
        }
        //修改状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_REFUND ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new CustomException ( "修改应收票据结算状态为退票失败！" );
        }
        return AjaxResult.success ( "应收票据退票成功" );
    }

    /**
     * 应收票据质押
     * 1、查询该应收票据是否已有质押单，如果有则不给质押，如果没有则新增
     * 2、修改源应收票据状态为质押状态
     * @param kingFinanceReceiptSettlementBillEntity
     * @return
     */
    @Override
    @Transactional (rollbackFor = Exception.class)
    public AjaxResult pledge (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectOne ( new QueryWrapper<KingFinanceReceiptBillEntity> ().eq ( "id", kingFinanceReceiptSettlementBillEntity.getReceiptBillId () ) );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        if ( receiptBillEntity.getSettlementStatus () == KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_RECITE ||
                receiptBillEntity.getSettlementStatus () == KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_PLEDGE ) {
            return AjaxResult.error ( "选中的单据为背书或质押状态，不能进行操作！" );
        }
        //新增应收票据结算单
        kingFinanceReceiptSettlementBillEntity = assemble ( kingFinanceReceiptSettlementBillEntity, receiptBillEntity );
        kingFinanceReceiptSettlementBillEntity.setDocTypeCode ( KingConstUtil.KING_RECEIPT_BILL_PLEDGE );
        kingFinanceReceiptSettlementBillEntity.setBizTime ( kingFinanceReceiptSettlementBillEntity.getPledgeTime () );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyType ( receiptBillEntity.getPayDeptType () );
        kingFinanceReceiptSettlementBillEntity.setTransactionCompanyId ( receiptBillEntity.getPayDeptId () );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillType ( 6 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( kingFinanceReceiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "新增应收票据质押结算单失败！" );
        }
        //修改源应收票据为质押状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_PLEDGE ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new RuntimeException ( "修改源应收票据为质押状态失败！" );
        }
        return AjaxResult.success ( "选中的票据质押成功" );
    }

    /**
     * 应收票据撤押：新增应收票据撤押结算单
     * 修改源应收票据状态为撤押状态
     * @param kingFinanceReceiptSettlementBillEntity
     * @return
     */
    @Override
    public AjaxResult unPledge (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity) {
        KingFinanceReceiptBillEntity receiptBillEntity = kingFinanceReceiptBillMapper.selectOne ( new QueryWrapper<KingFinanceReceiptBillEntity> ().eq ( "id", kingFinanceReceiptSettlementBillEntity.getReceiptBillId () ) );
        if ( receiptBillEntity == null ) {
            return AjaxResult.error ( "该票据不存在" );
        }
        if ( ! receiptBillEntity.getState ().equals ( ConstUtil.STATE_FINISH ) ) {
            return AjaxResult.error ( "选中的单据还没有审核，不能进行操作！" );
        }
        if ( receiptBillEntity.getSettlementStatus () != KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_PLEDGE ) {
            return AjaxResult.error ( "选中的单据结算状态不是质押状态，不能进行操作！" );
        }
        //新增应收票据撤押结算单
        kingFinanceReceiptSettlementBillEntity = assemble ( kingFinanceReceiptSettlementBillEntity, receiptBillEntity );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillType ( 7 );
        int i = iKingFinanceReceiptSettlementBillService.insertKingFinanceReceiptSettlementBillEntity ( kingFinanceReceiptSettlementBillEntity );
        if ( i == 0 ) {
            throw new RuntimeException ( "新增应收票据撤押结算单失败！" );
        }
        //修改源应收单据状态为撤押状态
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getSettlementStatus, KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_UN_PLEDGE ).
                eq ( KingFinanceReceiptBillEntity :: getId, receiptBillEntity.getId () ) );
        if ( ! update ) {
            throw new RuntimeException ( "修改源应收票据为质押状态失败！" );
        }
        return AjaxResult.success ( "选中的票据撤押成功" );
    }

    /**
     * 批量删除财务模块-应收票据,推金蝶
     * @param ids 需要删除的财务模块-应收票据,推金蝶ID
     * @return 结果
     */
    @Override
    public AjaxResult deleteKingFinanceReceiptBillEntityByIds (String[] ids) {
        boolean update = this.update ( new LambdaUpdateWrapper<KingFinanceReceiptBillEntity> ().
                set ( KingFinanceReceiptBillEntity :: getIsUsed, ConstUtil.IS_USED_NO ).
                in ( KingFinanceReceiptBillEntity :: getId, ids ) );
        if ( ! update ) {
            throw new CustomException ( "删除应收票据失败！" );
        }
        return AjaxResult.success ();
    }

    /**
     * 删除财务模块-应收票据,推金蝶信息
     * @param id 财务模块-应收票据,推金蝶ID
     * @return 结果
     */
    @Override
    public int deleteKingFinanceReceiptBillEntityById (String id) {
        return kingFinanceReceiptBillMapper.deleteKingFinanceReceiptBillEntityById ( id );
    }

    /**
     * 更新拆分的多条子应收票据
     * @param kingFinanceReceiptBillEntities
     * @param kingFinanceReceiptBillEntity
     * @return
     */
    private int updateReceiptBill (List<KingFinanceReceiptBillEntity> kingFinanceReceiptBillEntities, KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        if ( ! CollectionUtils.isEmpty ( kingFinanceReceiptBillEntities ) ) {
            KingFinanceReceiptBillEntity child = new KingFinanceReceiptBillEntity ();
            for ( int i = 0; i < kingFinanceReceiptBillEntities.size (); i++ ) {
                //复制父应收单据
                BeanUtils.copyProperties ( kingFinanceReceiptBillEntity, child, new String[]{"instanceId", "isSend", "isUsed"} );
                //将子的新内容塞进来
                KingFinanceReceiptBillEntity newChild = kingFinanceReceiptBillEntities.get ( i );
                child.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                //log.info ( "子公司-->{}", SecurityUtils.getCompanyId () );
                child.setDeptId ( CurrentUserUtil.getCompanyId () );
                child.setParentId ( kingFinanceReceiptBillEntity.getId () );
                child.setFaceAmount ( newChild.getFaceAmount () );
                child.setSubBillStartIndex ( newChild.getSubBillStartIndex () );
                child.setSubBillEndIndex ( newChild.getSubBillEndIndex () );
                //处理流水号
                //String billSerialNumber = kingFinanceReceiptBillEntity.getBillSerialNumber();
                //最后一位如果是数字或字母，则递增；否则拼接《-x》
                //int lastType = CommonUtil.checkEnd(billSerialNumber);
                //if (lastType == 1) {
                //取最后一位加1
                //int last = Integer.parseInt(billSerialNumber.trim().substring(billSerialNumber.length() - 1));
                //last += (i + 1);
                //child.setBillSerialNumber(billSerialNumber.concat(String.valueOf(last)));
                //} else {
                //取最后一位拼接字符串《-x》
                //child.setBillSerialNumber(billSerialNumber.concat("-").concat(String.valueOf(i + 1)));
                //}
                int count = this.count ();
                child.setBillSerialNumber ( "YSPJ".concat ( String.format ( "%08d", count ) ) );
                //处理票据号码=父的包+子票据区间
                child.setBillNo ( kingFinanceReceiptBillEntity.getBillPackNo ().concat ( "-" ).concat ( newChild.getSubPackInterval () ) );
                child.setSettlementStatus ( KingConstUtil.FINANCE_RECEIPT_BILL_SETTLEMENT_STATUS_EMPTY );
                child.setState ( ConstUtil.STATE_IN_DRAFT );
                child.setCreateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
                child.setCreateTime ( DateUtils.getNowDate () );
                boolean save = this.save ( child );
                if ( ! save ) {
                    throw new RuntimeException ( "新增拆分子应收票据失败！" );
                }
            }
        }
        return 1;
    }

    /**
     * 贴现、背书，收款业务中使用应收票据对象组装应收票据结算单
     * @param kingFinanceReceiptSettlementBillEntity
     * @param kingFinanceReceiptBillEntity
     * @return
     */
    private KingFinanceReceiptSettlementBillEntity assemble (KingFinanceReceiptSettlementBillEntity kingFinanceReceiptSettlementBillEntity, KingFinanceReceiptBillEntity kingFinanceReceiptBillEntity) {
        kingFinanceReceiptSettlementBillEntity.setDeptId ( CurrentUserUtil.getCompanyId () );
        kingFinanceReceiptSettlementBillEntity.setBillType ( kingFinanceReceiptBillEntity.getBillType () );
        kingFinanceReceiptSettlementBillEntity.setBillNo ( kingFinanceReceiptBillEntity.getBillNo () );
        kingFinanceReceiptSettlementBillEntity.setKingBaseCurrencyId ( kingFinanceReceiptBillEntity.getKingBaseCurrencyId () );
        kingFinanceReceiptSettlementBillEntity.setBillSerialNumber ( kingFinanceReceiptBillEntity.getBillSerialNumber () );
        kingFinanceReceiptSettlementBillEntity.setReceiptBillId ( kingFinanceReceiptBillEntity.getId () );
        kingFinanceReceiptSettlementBillEntity.setSettlementDeptId ( kingFinanceReceiptBillEntity.getSettlementDeptId () );
        kingFinanceReceiptSettlementBillEntity.setReceiptDeptId ( kingFinanceReceiptBillEntity.getReceiptDeptId () );
        return kingFinanceReceiptSettlementBillEntity;
    }

    /**
     * 更新应收票据背书明细列表
     * @param receiptBillReciteEntities
     * @param receiptBillId
     * @return
     */
    private int updateReceiptBillRecite (List<KingFinanceReceiptBillReciteEntity> receiptBillReciteEntities, String receiptBillId) {
        if ( ! CollectionUtils.isEmpty ( receiptBillReciteEntities ) ) {
            receiptBillReciteEntities.forEach ( receiptBillReciteEntity -> {
                receiptBillReciteEntity.setId ( SnowflakeIdWorker.getInstance ().nextStringId () );
                receiptBillReciteEntity.setReceiptBillId ( receiptBillId );
                receiptBillReciteEntity.setCreateBy ( SecurityUtils.getLoginUser ().getUser ().getUserId () );
                receiptBillReciteEntity.setCreateTime ( DateUtils.getNowDate () );
                int i = kingFinanceReceiptBillReciteMapper.insertKingFinanceReceiptBillReciteEntity ( receiptBillReciteEntity );
                if ( i == 0 ) {
                    throw new RuntimeException ( "更新背书列表明细失败！" );
                }
            } );
        }
        return 1;
    }


    /**
     * 根据往来单位类型，获取往来单位和付款单位
     * @param companyType：单位类型，根据往来单位或付款单位的类型魔法值
     * @param companyId：单位Id，根据单位类型，选择的具体单位Id
     * @return
     */
    private String getCompanyName (String companyType, String companyId) {
        if ( StringUtils.isBlank ( companyType ) || StringUtils.isBlank ( companyId ) ) {
            return "";
        }
        String transactionCompany = "";
        switch ( companyType ) {
            case "BD_Customer":
                CustomerEntity customerEntity = iCustomerService.getById ( companyId );
                transactionCompany = customerEntity.getCustomerName ();
                break;
            case "BD_Supplier":
                SupplierEntity supplierEntity = iSupplierService.getById ( companyId );
                transactionCompany = supplierEntity.getSupplierName ();
                break;
            case "FIN_OTHERS":
                KingBaseTransactionsCompanyEntity transactionsCompanyEntity = iKingBaseTransactionsCompanyService.getById ( companyId );
                transactionCompany = transactionsCompanyEntity.getTitle ();
                break;
            case "ORG_Organizations":
                SysDept organ = iSysDeptService.getById ( companyId );
                transactionCompany = organ.getDeptName ();
                break;
        }
        return transactionCompany;
    }

}
